{
    //有await和catch
    function f() {
        async function a() {
            console.log("1");
            await b();
            console.log("2");//b没有return，所以执行完b的同步任务后，在注册完b的第一个then，就注册了这里的then
        }

        async function b() {
            new Promise((resolve, reject) => {
                console.log(3);
                resolve("4");
                console.log("5");
            })
                .then(value => {
                    console.log(value);
                    throw new Error("6");
                })
                .then(() => { //不执行，因为前面的then报错了，后续的then全部catch
                    console.log(6);
                })
                .catch(r => {//执行
                    console.log(JSON.stringify(r));
                });
        }

        console.log("7");

        a();

        setTimeout(() => {
            console.log("8");
        }, 0);

        const p = new Promise((resolve, reject) => {
            console.log("9");
            resolve("10");
        }).then(value => {
            console.log(value);
        });

        p.then(value => {
            console.log("p:then", value);
        });

        console.log("script end");
    }

    //示例一 - then中返回promise
    const a = () => {
        Promise.resolve(0)
            .then(() => {
                console.log(0);
                return Promise.resolve(4);
            })
            .then((res) => console.log(res));

        Promise.resolve()
            .then(() => {
                console.log(1);
            })
            .then(() => {
                console.log(2);
            })
            .then(() => {
                console.log(3);
            })
            .then(() => {
                console.log(5);
            })
            .then(() => {
                console.log(6);
            })
    }

    //示例二 - 普通示例
    const b = () => {
        console.log('script start');

        setTimeout(() => {

            console.log('setTimeout');

        });

        new Promise<void>((resolve, reject) => {

            console.log('promise');

            resolve();

        }).then(function () {

            console.log('promise1');

        }).then(function () {

            console.log('promise2');

        });

        console.log('script end');
    }

    //示例三 - 清空微任务队列再执行宏任务
    const c = () => {
        setTimeout(() => {
            new Promise<void>(resolve => {
                resolve();
            }).then(() => {
                console.log('test');
            });

            console.log(4);
        });

        new Promise<void>(resolve => {
            resolve();
            console.log(1)
        }).then(() => {
            console.log(3);
            Promise.resolve().then(() => {
                console.log('before timeout');
            }).then(() => {
                Promise.resolve().then(() => {
                    console.log('also before timeout')
                })
            })
        })
        console.log(2);


    }

    // Tip: commonJS和ESModule模式，下面的两个结果不同：主要区别在于then和nextTick的顺序，详细见语雀笔记。 （总体还是nextTick比微任务更快执行）

    //示例4 - 有nextTick
    // CommonJS模式 - 普通分析即可
    // 在esm模式中， 由于esm会被包裹在await后执行，所以相当于第一轮代码执行是微任务，这时候的NextTick需要等待微任务清空完成后才能执行。所以先输出 8 再 6。
    // 后续在time1中又遇到了nextTick和微任务同时出现的情况，这时候就是普通宏任务环境了，所以 nextTick优先级高于微任务， 先输出 3 再 5
    const d = () => {
        console.log('1');
        setTimeout(function () {//time1
            console.log('2');
            new Promise<void>(function (resolve) {
                console.log('4');
                resolve();
            }).then(function () {//then1
                console.log('5')
            })
            process.nextTick(function () {//next1
                console.log('3');
            })
        })
        process.nextTick(function () {//next2
            console.log('6');
        })
        new Promise<void>(function (resolve) {
            console.log('7');
            resolve();
        }).then(function () {//then2
            console.log('8')
        })
        setTimeout(function () {//time2
            console.log('9');
            process.nextTick(function () {//next3
                console.log('10');
            })
            new Promise<void>(function (resolve) {
                console.log('11');
                resolve();
            }).then(function () {//then3
                console.log('12')
            })
        })
    }

    //示例5 - 有nextTick + setImmediate
    const e = () => {
        setImmediate(function () {
            console.log(1);
        });
        setTimeout(function () {
            console.log(2);
        }, 0);
        new Promise<void>(function (resolve) {
            console.log(3);
            resolve();
            console.log(4);
        }).then(function () {
            console.log(5);
        });
        console.log(6);
        process.nextTick(function () {
            console.log(7);
        });
        console.log(8);
    }

}